package com.bkhc.file.service;

import com.alibaba.excel.util.StringUtils;
import com.bkhc.common.exception.CustomException;
import com.bkhc.common.exception.FileException;
import com.bkhc.common.util.response.ResultCode;
import com.bkhc.common.util.response.ResultJson;
import com.bkhc.file.entity.FileBean;
import com.bkhc.file.repository.FileBeanRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Date;
import java.util.Optional;

@Component
@Slf4j
public class FileService {
    @Autowired
    private FileBeanRepository repository;

    private Path path;

    private Path productFilepath;

    private Path vedioPath;

    public FileService(@Value("${file.upload.path}")String path,@Value("${product.file.upload.path}")String productFilepath,@Value("${product.video.upload.path}")String  vedioPath) {
        this.path = Paths.get(path).toAbsolutePath().normalize();
        this.productFilepath = Paths.get(productFilepath).toAbsolutePath().normalize();
        this.vedioPath = Paths.get(vedioPath).toAbsolutePath().normalize();
        try {
            Files.createDirectories(this.path);
            Files.createDirectories(this.productFilepath);
            Files.createDirectories(this.vedioPath);
        } catch (IOException e) {
            throw new FileException("Could not create the directory", e);
        }
    }

    public String uploadFile(MultipartFile file) {
        String fileName = file.getOriginalFilename();
        try {
            // Check if the file's name contains invalid characters
            if(fileName.contains("..")) {
                throw new FileException("Sorry! Filename contains invalid path sequence " + fileName);
            }
            String filetype = fileName.substring(fileName.indexOf("."),fileName.length());
            // Copy file to the t arget location (Replacing existing file with the same name)
            Path targetLocation = path.resolve(System.currentTimeMillis()+filetype);
            Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
            FileBean fileBean = new FileBean();

            fileBean.setFileName(fileName);
            fileBean.setFilePath(targetLocation.toAbsolutePath().toString());
            repository.save(fileBean);
            return fileBean.getFileId();
        } catch (IOException ex) {
            throw new FileException("Could not store file " + fileName + ". Please try again!", ex);
        }
    }

    public Resource downloadFile(String fileId) {
        FileBean fileBean = repository.findByFileId(fileId);
        if(fileBean==null){
            throw new CustomException(ResultJson.failure(ResultCode.BAD_REQUEST));
        }
        File file = new File(fileBean.getFilePath());
        if (!file.exists()) {
            throw new CustomException(ResultJson.failure(ResultCode.OPERATE_ERROR));
        }
        Path filePath = path.resolve(fileBean.getFilePath()).normalize();
        Resource resource = null;
        try {
            resource = new UrlResource(filePath.toUri());
            if(resource.exists()) {
                return resource;
            } else {
                throw new FileException("File not found " + fileBean.getFileName());
            }
        } catch (MalformedURLException  ex) {
            throw new FileException("File not found " + fileBean.getFileName(), ex);
        }
    }

    public String uploadProductFile(MultipartFile file,String productCode) {
        String fileName = file.getOriginalFilename();
        try {
            // Check if the file's name contains invalid characters
            if(fileName.contains("..")) {
                throw new FileException("Sorry! Filename contains invalid path sequence " + fileName);
            }
            String filetype = fileName.substring(fileName.indexOf("."),fileName.length());
            // Copy file to the t arget location (Replacing existing file with the same name)
            Path targetLocation = productFilepath.resolve(productCode+File.separator+System.currentTimeMillis()+filetype);
            Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
            FileBean fileBean = new FileBean();
            fileBean.setFileName(fileName);
            fileBean.setFilePath(targetLocation.toAbsolutePath().toString());
            repository.save(fileBean);
            return fileBean.getFileId();
        } catch (IOException ex) {
            throw new FileException("Could not store file " + fileName + ". Please try again!", ex);
        }
    }

    public String uploadProductVedio(MultipartFile file, String productCode) {
        String fileName = file.getOriginalFilename();
        try {
            // Check if the file's name contains invalid characters
            if(fileName.contains("..")) {
                throw new FileException("Sorry! Filename contains invalid path sequence " + fileName);
            }
            String filetype = fileName.substring(fileName.indexOf("."),fileName.length());
            // Copy file to the t arget location (Replacing existing file with the same name)
            Path targetLocation = vedioPath.resolve(productCode+File.separator+System.currentTimeMillis()+filetype);
            Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
            FileBean fileBean = new FileBean();
            fileBean.setFileName(fileName);
            fileBean.setFilePath(targetLocation.toAbsolutePath().toString());
            repository.save(fileBean);
            return fileBean.getFileId();
        } catch (IOException ex) {
            throw new FileException("Could not store file " + fileName + ". Please try again!", ex);
        }
    }
}
